package com.jinzecloud.reportapproval.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.deepoove.poi.config.Configure;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.jinzecloud.reportapproval.bean.*;
import com.jinzecloud.reportapproval.dto.AdminDto;
import com.jinzecloud.reportapproval.dto.AuditParam;
import com.jinzecloud.reportapproval.dto.DataStagingParam;
import com.jinzecloud.reportapproval.enums.AuditRoleEnums;
import com.jinzecloud.reportapproval.enums.StateEnum;
import com.jinzecloud.reportapproval.enums.TableEnums;
import com.jinzecloud.reportapproval.utils.*;
import com.jinzecloud.reportapproval.vo.AuthenticationTaskVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.jinzecloud.reportapproval.mapper.AuthenticationTaskMapper;
import com.jinzecloud.reportapproval.service.AuthenticationTaskService;

import javax.servlet.http.HttpServletRequest;


@Service("authenticationTaskService")
public class AuthenticationTaskServiceImpl extends ServiceImpl<AuthenticationTaskMapper, AuthenticationTask> implements AuthenticationTaskService {

    @Autowired
    private AuthenticationTaskMapper authenticationTaskMapper;
    @Autowired
    private FileUploadUtil fileUploadUtil;
    @Autowired
    private HttpServletRequest request;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String key = (String) params.get("key");
        MPJLambdaWrapper<AuthenticationTask> authenticationTaskMPJLambdaWrapper = new MPJLambdaWrapper<>();
        authenticationTaskMPJLambdaWrapper
                .select(AuthenticationTask::getId,AuthenticationTask::getStatus,AuthenticationTask::getIdentificationBasis,AuthenticationTask::getProjectNumber,AuthenticationTask::getProjectType,AuthenticationTask::getSamplingSample,AuthenticationTask::getProduct,AuthenticationTask::getModel,AuthenticationTask::getCompanyName,AuthenticationTask::getAddress,AuthenticationTask::getContact,AuthenticationTask::getPhone,AuthenticationTask::getSamplingAmount,AuthenticationTask::getDeadline)
                .select(Product::getPrProjectName)
                .leftJoin(Product.class, Product::getPrId, AuthenticationTask::getProduct);
        if (!StringUtils.isBlank(key)){
            authenticationTaskMPJLambdaWrapper
                    .like(AuthenticationTask::getProjectNumber,key).or()
                    .like(AuthenticationTask::getProduct,key).or()
                    .like(AuthenticationTask::getModel,key).or()
                    .like(AuthenticationTask::getCompanyName,key).or()
                    .like(AuthenticationTask::getAddress,key).or()
                    .like(AuthenticationTask::getContact,key).or()
                    .like(AuthenticationTask::getPhone,key);
        }

        IPage<AuthenticationTaskVo> page = authenticationTaskMapper.selectJoinPage(
                new Page<AuthenticationTaskVo>(Long.parseLong((String) params.get("page")), Long.parseLong((String) params.get("limit"))),
                AuthenticationTaskVo.class,
                authenticationTaskMPJLambdaWrapper
        );
        PageUtils pageUtils = new PageUtils(page);

        return pageUtils;
    }

    @Override
    public R audit(AuditParam auditParam) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        List<AdminDto> adminDos = AuditUtil.getAdminDto(authentication.getName());
        if (CollectionUtil.isEmpty(adminDos)) return R.error("您没有审核权限！");
        AuthenticationTask authenticationTask = this.getById(auditParam.getId());
        int state = authenticationTask.getStatus();
        if (!auditParam.isState()) {
            updateById(authenticationTask.setStatus(StateEnum.APPROVAL_NOT_PASS.getState())
                    .setAuditOpinion(auditParam.getAuditOpinion())
                    .setAuditDate(DateUtil.date().toDateStr()));
            return R.ok();
        }
        StateEnum currentAuditState = AuditUtil.getStateText(TableEnums.TESTS_SUMMARY_TABLE_SERVICE.getTableName(), state);
        Integer nextAuditStateIndex = AuditUtil.getNextAuditState(TableEnums.TESTS_SUMMARY_TABLE_SERVICE.getTableName(), state, adminDos.stream().map(AdminDto::getRoleCode).toList());
        AdminDto adminDto = adminDos.stream().filter(a -> StrUtil.equals(a.getRoleCode(), currentAuditState.getAuditRole()))
                .findFirst().orElse(null);
        if (adminDto == null || nextAuditStateIndex == null) return R.error("您没有审核权限！");
        if (StrUtil.equals(adminDto.getRoleCode(), AuditRoleEnums.CHECKER_PERSON.getCode())) authenticationTask.setSignaturePerson(adminDto.getAdSignature());authenticationTask.setResponsibleTime(new SimpleDateFormat("yyyy-MM-dd HH:ss:mm").format(new Date()));
        if (StrUtil.equals(adminDto.getRoleCode(), AuditRoleEnums.RECORDER.getCode())) authenticationTask.setSignatureLeader(adminDto.getAdSignature());authenticationTask.setOpinionDirector(new SimpleDateFormat("yyyy-MM-dd HH:ss:mm").format(new Date()));
        if (StrUtil.equals(adminDto.getRoleCode(), AuditRoleEnums.CHECKER.getCode())) authenticationTask.setMastersInstructions(adminDto.getAdSignature());authenticationTask.setInstructionsTime(new SimpleDateFormat("yyyy-MM-dd HH:ss:mm").format(new Date()));
        authenticationTask.setStatus(nextAuditStateIndex)
                .setAuditOpinion(auditParam.getAuditOpinion())
                .setAuditDate(DateUtil.date().toDateStr());
        updateById(authenticationTask);
        return R.ok();
    }

    @Override
    public Object auditList(DataStagingParam param) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LambdaQueryWrapper<AuthenticationTask> queryWrapper = new LambdaQueryWrapper<>();
        List<AdminDto> adminDto = AuditUtil.getAdminDto(authentication.getName());
        Set<Integer> roleSet = adminDto.stream().map(a -> StateEnum.getStateEnumByAuditRole(a.getRoleCode()).getState()).collect(Collectors.toSet());
        roleSet.remove(StateEnum.UN_SUBMIT.getState());
        queryWrapper.in(AuthenticationTask::getStatus, roleSet);
        return page(new Page<>(param.getPageNo(), param.getPageSize()), queryWrapper);
    }

    @Override
    public String export(Integer id) {
        AuthenticationTask authenticationTask = getById(id);
        if (authenticationTask != null) {
            AuthenticationTaskVo authenticationTaskVo = new AuthenticationTaskVo();
            BeanUtil.copyProperties(authenticationTask, authenticationTaskVo);
            authenticationTaskVo.setIdentificationBasis(authenticationTask.getIdentificationBasis() + " " + authenticationTask.getProduct());
        }
        JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(authenticationTask));
        File tempFile = WordUtil.getWordFile("template/jdrwtzd.docx", data, Configure.builder());
        String fileName = "鉴定任务通知单";
        String uploadDirectory = fileUploadUtil.getUploadFilePath("temp");
        String filePath = uploadDirectory + authenticationTask.getProduct() + fileName;
        String savePath = RequestUtils.getBasePath(request) + "upload/temp/" + authenticationTask.getProduct() +fileName;
        FileUtil.copy(tempFile, new File(filePath + ".docx"),true);
        PDFUtil.WordToPdf(tempFile, new File(filePath + ".pdf"));
        this.update(new LambdaUpdateWrapper<AuthenticationTask>().set(AuthenticationTask::getWordPath, savePath + ".docx").set(AuthenticationTask::getPdfPath, savePath + ".pdf").eq(AuthenticationTask::getId, id));
        return RequestUtils.getBasePath(request) + "upload/temp/" + authenticationTask.getProduct() + fileName + ".pdf";
    }

    public String exportWord(Integer id) {
        AuthenticationTask authenticationTask = getById(id);
        if (authenticationTask != null) {
            AuthenticationTaskVo authenticationTaskVo = new AuthenticationTaskVo();
            BeanUtil.copyProperties(authenticationTask, authenticationTaskVo);
            authenticationTaskVo.setIdentificationBasis(authenticationTask.getIdentificationBasis() + " " + authenticationTask.getProduct());
        }
        JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(authenticationTask));
        File tempFile = WordUtil.getWordFile("template/jdrwtzd.docx", data, Configure.builder());
        String fileName = "鉴定任务通知单";
        String uploadDirectory = fileUploadUtil.getUploadFilePath("temp");
        String filePath = uploadDirectory + authenticationTask.getProduct() + fileName;
        String savePath = RequestUtils.getBasePath(request) + "upload/temp/" + authenticationTask.getProduct() +fileName;
        FileUtil.copy(tempFile, new File(filePath + ".docx"),true);
        PDFUtil.WordToPdf(tempFile, new File(filePath + ".pdf"));
        this.update(new LambdaUpdateWrapper<AuthenticationTask>().set(AuthenticationTask::getWordPath, savePath + ".docx").set(AuthenticationTask::getPdfPath, savePath + ".pdf").eq(AuthenticationTask::getId, id));
        return RequestUtils.getBasePath(request) + "upload/temp/" + authenticationTask.getProduct() + fileName + ".docx";
    }

    @Override
    public String viewPdf(Integer id) {
        String s = export(id);
        return s;
    }

    @Override
    public AuthenticationTask getInfo(String projectNumber) {
        AuthenticationTask authenticationTask = getOne(new LambdaQueryWrapper<AuthenticationTask>().eq(AuthenticationTask::getProjectNumber, projectNumber));
        if (authenticationTask == null) return null;
        authenticationTask.setIdentificationBasis("DG/T " + authenticationTask.getIdentificationBasis() + " 《" + authenticationTask.getProduct() + "》");
        return authenticationTask;
    }

    @Override
    public R saveAuthenticationTask(AuthenticationTask authenticationTask) {
        QueryWrapper<AuthenticationTask> authenticationTaskQueryWrapper = new QueryWrapper<>();
        authenticationTaskQueryWrapper.eq("project_number", authenticationTask.getProjectNumber());
        AuthenticationTask authenticationTask1 = getOne(authenticationTaskQueryWrapper);
        if (authenticationTask1 != null){
            return R.error("项目编号已存在");
        }else{
            save(authenticationTask);
        }
        return R.ok();
    }

    @Override
    public String viewWord(Integer id) {
        String s = exportWord(id);
        return s;
    }

    @Override
    public AuthenticationTask getSampleSheet(String projectNumber) {
        QueryWrapper<AuthenticationTask> taskQueryWrapper = new QueryWrapper<AuthenticationTask>().eq("project_number", projectNumber);
        AuthenticationTask authenticationTask = getOne(taskQueryWrapper);
        return authenticationTask;
    }

}